ε Programación de demos ε --------------------- Bienvenidos a la nueva sección sobre programación de efectos gráficos en la PhyMosys Magazine. El encargado de llevarla a cabo soy yo, mi handle es Matrix, soy coder del grupo Dosis. En mi curriculum scenero se encuentran dos megademos y una intro de 4Kb, mi party atendance en estos momentos es de 3 Euskals, 2 Queima- das, 1 Arroutada y 1 Festa. En Dosis principalmente me encargo de las 3D, pero he trabajado y suelo trabajar (cuando me dejan :) en todo tipo de efectos. Una vez presentado, vayamos al grano. El objetivo de esta sección es enseñar algoritmos de efectos gráficos, si no sabes programar o sabes pero nunca has hecho programación gráfica mejor empieza por otras secciones del magazine. Como primer artículo, con el permiso de Skynet, voy a realizar una pequeña incursion en el mundo de las 3D y a repasar unos cuantos efectos gráficos básicos. Efectos clásicos: φ - Fuego Junto con la rotación 2D este ha debido ser el efecto gráfico más codeado de todos los tiempos. Su inventor es Jare / Iguana, lo descubrió investigando nuevos tipos de plasma allá por el 93, apareció por primera vez en la demo Inconexia, y a partir de entonces el efecto se ha hecho mundialmente conocido, hasta en la publicidad de Nintendo se ha visto el efecto fuego. Incluso se tienen hecho (y aún se siguen haciendo) concursos para ver quien crea este efecto en el menor tamaño. La version más pequeña y funcional que he visto de este efecto la hizo WiseFox / Alien en apenas 60 y pocos bytes. Jare, tenías que haberlo patentado, te hubieras hecho de oro. :D Fuera bromas, el efecto es sencillo, la paleta ha de ser un degradado negro-rojo-amarillo-blanco, en la parte inferior de pantalla se dibuja una lí- nea con valores aleatorios, a cada punto de la pantalla se le aplica la media de la suma de los puntos de alrededor. El tipo de cálculo en la media varía el efecto. φ - Rotozoom Este es otro efecto de los clásicos que debería programar todo el mundo, es una primera incursión obligatoria en el uso de trigonometría para efectos gráficos. Quizá el más clásico de todos los rotazooms en PC sea el que aparece en la Second Reality / Future Crew. La idea de este efecto es obtener los incrementos X e Y a partir del ángulo de giro, estos incrementos se sumaran al puntero a la textura y son constantes en cada linea de pixels (scanline) con lo que el bucle interno (inner loop) se puede optimizar bastante. El incremento se puede escalar usando decimales en coma fija, con lo que obtenemos la sensacion de zoom, ya que a incrementos más pequeños, más zoom se conseguirá. Uno de los problemas de este efecto en los Pentium, es que debido al caché interno de estos, en ciertos ángulos la velocidad aumentará y en otros decrecerá. Esto es debido a que el caché trabaja con líneas y si coincide que estamos cambiando de líneas muy poco obtendremos menos fallos de caché y por lo tanto más velocidad, si por el contrario coincide que en ese ángulo hay que cambiar de línea a cada pixel, solo obtendremos fallos de caché, con lo que la velocidad decrecerá. Para evitar esto se puede realizar el efecto en bloques de 32x32 bytes (16x16 o 8x8 dependiendo del tamaño de la linea de caché (32 bytes en Pentium)) para asi asegurarse que no halla fallos de caché hasta que no se cambie de bloque, como los fallos de caché son pocos pero constantes se obtiene una velocidad fija bastante alta. Esta técnica viene explicada en un tutorial de Pascal (el creador del Cubic Player) que se puede encontrar en los lugares habituales. El rotazoom más rápido del que tengo constancia son 380 fps en un P120 (320x200 256 colores) realizado por Geiger / Dosis en ensamblador puro. φ - Plasma Otro efecto asiduo a intros de 4Kb y demás efectos rápidos. Para mi los mejores siempre han sido los de Tran en sus demos Ambience, Luminati, etc... Teniendo un fractal de tipo plasma ya generado (o generandolo en tiempo real que no es demasiado lento) se guarda en un buffer. A continuacion se crean dos o más punteros (dependiendo del número de planos) que apuntan a partes del plasma y se vuelcan en pantalla sumándose todos los planos. Los punteros ten- dran un movimiento independiente y diferente. Cuantos más planos, más lento, más suave, más bonito. Limitando la altura del plasma a un número determinado por 256/número de planos, no tendremos que hacer comprobaciones de desborda- miento. Servir con una paleta lineal generada con buen gusto y a ser posible añadir unos cuantos efectos a esta. :) φ - Tunel texturado Aunque no es un efecto clásico (tardó bastante relativamente en ponerse de moda), empieza a serlo. El primero que vi aparece en la HeartQuake / Iguana, y desde entonces se han ido multiplicando hasta plagar todo tipo de demos e intros. Personalmente opino que los más bonitos son los de la Luminati / Tran, y el más peculiar el de la Stars / Nooon, mezcla de tunel y voxel. El efecto es de concepción sencilla, se calcula la distancia de todos los puntos de la pantalla al centro de la pantalla, y a partir de ese valor y del ángulo relativo que forman respecto a ese eje se les asigna una dirección a una textura. Esa dirección se guarda ya que permanece constante. Despues se realiza una rutina que dibuje en pantalla la textura a partir de las direcciones almacenadas para cada pixel. Si a la dirección se le suma un incremento varia- ble obtendremos el movimiento de la textura dentro del tunel, dando la sensa- ción de movimiento. El método de hallar la dirección a partir del ángulo y la distancia al cen- tro puede variar, lo que da lugar a muchas formas y maneras de hacer un tunel texturado. φ - Landscape El nombre viene a significar un efecto de simulación de terreno. Hay de muchos tipos: por pixels ( Unreal / Future Crew ), por bloques de altura y anchura variable llamados voxels ( Comanche / Novalogic, HeartQuake / Iguana ), por poligonos ( Mars / Tim Clark ), etc... El sistema es sencillo, el terreno lo obtenemos de un fractal tipo plasma, del cual sacamos las coordenadas x,y en el espacio a partir de las coordenadas x,y de cada pixel en el plasma, y la altura en el espacio (z) del valor del pixel. Una vez tenemos las coordenadas x,y,z de los puntos solo hay que proyectarlas en pantalla a ser posible en perspectiva para dar sensación de profundidad y realzar el efecto de "scape" del landscape. :D Ω Técnicas avanzadas: φ - El triángulo es un polígono de 4 lados Y quien diga lo contrario es que no ha hecho una rutina de rellenado de polígonos decente. :D El rellenado de polígonos es uno de los quebraderos de cabeza de todo aquel que se mete en el mundo de las 3D, la verdad es que un algoritmo mal hecho fre- na bastante las 3D, y el optimizar el algoritmo no es viable si el planteamien- to no es bueno. Ante todo es mejor cargarse con lapiz, papel y una buena "do- sis" de paciencia. ;) Tenemos 3 vertices, definidos por sus coordenadas x1,y1,x2,y2,x3,y3. Si unimos los vertices con líneas tendremos un triángulo. En realidad si estudia- mos el triángulo con calma podemos ver que tiene dos partes, en general hay un vertice que está arriba, uno en el medio, y otro abajo, asi que lo mejor será ordenarlos por la altura. Asi que ordenamos x1,y1,x2,y2,x3,y3 por altura y los llamamos xh,yh,xm,ym,xl,yl (h=high, m=medium, l=low). Si seguimos estudiando el triángulo vemos que el vertice medio (xm,ym) defi- ne el sitio donde más ancho es el triángulo. Y que ese vertice medio puede es- tar tanto a la derecha como a la izquierda del triángulo. Asi que mejor que reflejemos este conocimiento en nuestras variables. Pero con los datos que tenemos no podemos saber si esta a la izquierda o a la dere- cha respecto al lado contrario, con lo que lo que tenemos que hacer es averi- guar que coordenada tiene ese lado a la altura de ym. Es decir, creamos un cuarto vertice en el lado que va desde xh,yh a xl,yl a la altura de ym. Espero que estes dibujando porque sino es un poco difícil de ver. Para hallar ese vertice hacemos lo siguiente: x4 = xh+(xm-xh)*(xl-xh)/(yl-yh) y4 = ym Hala, ya tenemos el cuarto vertice, ahora podemos saber si el vertice medio esta a la izquierda o a la derecha del triangulo mirando si xm es mayor o menor de x4. Lo mejor que podemos hacer es utilizar variables nuevas llamadas xmi,ymi,xmd,ymd y meter en ellas los dos vertices medios segun esten a la derecha o a la izquierda. Bien, ya tenemos cuatro vertices, xh,yh,xmi,ymi,xmd,ymd,xl,yl hemos transformado un triangulo en un cuadrado en el que uno de sus angulo internos mide 180º. :)) Esta es la idea principal de este algoritmo, el dividir el triangulo en dos triangulos con un lado horizontal. Por el momento nos vamos a olvidar de la parte inferior del triangulo. El dibujado se va a realizar haciendo lineas horizontales de puntos para cada y. Para saber el numero de lineas horizontales que tenemos que hacer solo hay que restar ymi - yh (recordar que estamos trabajando con coordenadas de pantalla en las que yl>ym>yh), las lineas horizontales parten de una x determinada a otra x, para ymi e ymd estas seran xmi y xmd, y para yh estas seran la misma (xh), asi que tenemos que calcular las x intermedias para cada linea de pantalla (scanline). Este es otro de los quizs del algoritmo, interpolar datos. Interpolar es hallar datos intermedios entre dos valores, y se halla multiplicando la posicion del dato a averiguar por el delta de interpolacion y sumandolo al dato de partida, ese delta se calcula dividiendo la diferencia de los dos datos entre la distancia que los separa. Es decir, para saber que x del lado izquierdo le corresponde la linea 5, será: delta = (dato destino - dato partida) / distancia = (xmi-xh)/(ymi-yh) Ahora para saber cual es la X para la y correspondiente a la quinta linea solo hay que hacer x = 5 * delta + yh. Asi que hacemos un bucle que recorre el triangulo: Γ delta_de_x_izquierdo=(xmi-xh)/(ymi-yh) Γ delta_de_x_derecho=(xmd-xh)/(ymd-yh) Γ for y=0 to ymi-yh Γ { Γ x_izq=y*delta_de_x_izq+yh Γ x_der=y*delta_de_x_der+yh Γ for x=x_izq to x_der Γ { Γ putpixel(x,y,color) Γ } Γ } Esto rellenara la parte superior del triangulo, el algoritmo para rellenar la parte inferior es similar: Γ delta_de_x_izquierdo=(xl-xmi)/(yl-ymi) Γ delta_de_x_derecho=(xl-xmd)/(yl-ymd) Γ for y=0 to yl-ymi Γ { Γ x_izq=y*delta_de_x_izq+ymi Γ x_der=y*delta_de_x_der+ymd Γ for x=x_izq to x_der Γ { Γ putpixel(x,y,color) Γ } Γ } Ala, ya está dibujado el triangulo entero. Asi de fácil. Por supuesto esto es muy optimizable, partiendo que en vez de usar multiplicaciones se pueden usar incrementos en coma fija y otras historias a gusto del consumidor. Como podeis ver una vez hecho el planteamiento, el dibujado es muy rápido y sencillo, lo que hara un algoritmo fácil de optimizar y muy, muy rápido. Peeeero algunos estareis pensando que hay triángulos en los que el vértice superior o inferior tiene la misma altura que el vértice medio. Cierto, pero para estos casos solo hay que mirar antes de dibujar esa parte que su altura es superior a 0. Bueno, espero no haberos liado demasiado y que tengáis que recomponer el algoritmo de cálculo de vertices a partir de los bucles de dibujado. Tampoco os voy a escribir todo el código, y realmente ya he escrito más del que hubiera querido, pero a veces es mejor no liar las cosas. :)) Sobre todo intentad entender el concepto de interpolar, es fundamental en la optimización de efectos gráficos. Pensad que lo que nos permite es averiguar muchos datos a partir de dos datos de una manera facil y rápida. Muchas veces nos encontraremos con datos difíciles de obtener y de cálculos costosos, la solución es calcular solo un par y hayar los otros por interpolación en la medida de lo posible. Por cierto, esto de interpolar a muchos os sonará de los scanners. Cuando en un scanner se dice que se obtiene una resolución por interpolación significa que parte de los datos los calcula a partir de interpolar dos datos reales. Y como los que cuentan son los datos reales no os dejéis engañar y mirad siempre la resolución máxima óptica del scanner y no la interpolada. ;) Bueno, hasta aqui llega el episodio de hoy. Los que tengáis dudas me mandáis un email y los que queráis que explique algún efecto (sea cual sea) o queréis comentarme algo pues tambien me mandais una misiva, que para algo esta Internet a parte de para conseguir fotos porno O:D, os complaceré en la medida de lo posible. :) ∞ Matrix / Dosis ∞ thematrix@biosys.net ∞ www.geocities.com/SoHo/1024 ∞ www.geocities.com/SoHo/1024/dosis.html